/**
 * 
 */
package org.bitmap.mm.util;

import java.io.File;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.util.Log;
import android.view.WindowManager;
import android.widget.ImageView;

/**
 * Bitmap管理类,负责Bitmap网络下载缓存,内存管理，防止OOM内存溢出问题.</br>
 * 图片默认缓存到SDCard卡中，/sdcard/Android/data/$You_App_PackageName/ </br>
 * 大概有4种图片加载方法，ICON图标加载方法，中、大图片加载方法.</br>
 * 图片下载有单线程和多线程，线程池 Executors.newFixedThreadPool(5);<br>
 * 方法带有AsTasks的就是多线程下载图片</br>
 * 
 * -----------------------------------------</br>
 * </br>
 * 创建图片管理器</br>
 * LoveBitmapManager bm = new LoveBitmapManager(getApplication());</br>
 * 获得图片缓存管理器</br>
 * ImageCaches imageCaches = bm.getImageCaches();</br>
 * 获取本地已经缓存的图片</br>
 * Bitmap bitmap = getBitmapFromDiskCache("图片的url地址", 0, null);</br>
 * </br>
 * -----------------------------------------</br>
 * 单纯的下载图片不许要显示到ImageView中,也不许要相应的缓存管理介入</br>只是负责下载图片文件然后保存到本地目录----------------</br>
 * Stirng imageurl="你的图片的http地址";</br>
 * bm.loveSimpleLoadBitmap(imageurl, this); this是数据回调接口{@link OnFetchCompleteListener}</br>
 * 图片下载完后{@link OnFetchCompleteListener} 接口回调会得到图片本地的File,</br>
 * 可以自由加载文件，图片的缩放、压缩等二次操作可自由发挥
 *-------------------------------------------</br>
 *  
 * 
 * 
 * 
 * -----------------------------------------</br>
 * @author hljdrl@gmail.com 爱生活、少加班、多关爱身边的人、代码之美、架构之美、代码审美...</br>
 * 
 */
public final class LoveBitmapManager {

	public static final String TAG = "BitmapManager";
	private static boolean mDebug = false;
	private static final int FADE_IN_TIME = 200;
	protected Bitmap mLoadingBitmap;
	protected boolean mFadeInBitmap = true;
	private boolean mExitTasksEarly = false;
	protected Context mContext;
	protected ImageCaches mImageCache;
	private LoveBitmapTask mBitmapThread;
	private LoveBitmapHandler loveBitmapHandler;
	private ExecutorService  executorService ;
	int screenWidth;
	int screenHeight;
	/**
	 * @param context
	 */
	public LoveBitmapManager(Context context) {
		mContext = context;
		mImageCache = new ImageCaches(mContext);
		executorService = Executors.newFixedThreadPool(5);
		loveBitmapHandler = new LoveBitmapHandler(mImageCache, this);
		mBitmapThread = new LoveBitmapTask(this,new LoveBitmapHandler(mImageCache,this));
		WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
		screenWidth = wm.getDefaultDisplay().getWidth();
		screenHeight = wm.getDefaultDisplay().getHeight();
		mBitmapThread.start();
	}
	LoveBitmapHandler getDefaultLoveBitmapHandler()
	{
		return loveBitmapHandler;
	}
	public void shutdownAsTask()
	{
		try{
		if(executorService!=null){
			executorService.shutdown();
		}
		if(mBitmapThread!=null){
			mBitmapThread.setRunning(false);
			mBitmapThread.clear();
		}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	public Context getContext() {
		return mContext;
	}
	public static void setDebug(boolean debug) {
		mDebug = debug;
	}

	public static boolean isDebug() {
		return mDebug;
	}
	/**
	 * 清楚图片资源缓存
	 */
	public final void clearCaches() {
		if (mImageCache != null) {
			mImageCache.clearCaches();
		}
	}

//	/**
//	 * @param url
//	 * @return
//	 */
//	private Bitmap loadBitmapFromDiskCache(String url, Options opts,
//			int reqWidth, Bitmap.Config cofnig) {
//		return mImageCache.getBitmapFromDiskCache(url, reqWidth, cofnig);
//	}

	/**
	 * @return ImageCaches 缓存管理器
	 */
	public ImageCaches getImageCaches() {
		return mImageCache;
	}
	/**
	 * 本地文件是否存在这张图片
	 * @param data 图片的URL
	 * @return 本地文件是否存在这张图片
	 */
	public boolean hasImageAsLocationFile(String data){
		if(mImageCache!=null)
			return mImageCache.hasImageAsLocationFile(data);
		
		return false;
	}
	/**
	 * 获得指定图片在本地文件的完整路径
	 * @param data 图片的URL
	 * @return 图片的本地FILE路径
	 */
	public File getImageAsLoctionFile(String data){
		if(mImageCache!=null)
			return mImageCache.getImageAsLocationFile(data);
		
		return null;
	}
	/**
	 * @param data
	 *            图片URL
	 * @param image
	 *            view组件
	 * @param imageWidth
	 *            图片的宽度,可以设置小于0的数字，大于0则按照图片宽度缩放图片.
	 * @param config
	 *            Bitmap.Config 颜色加载模式
	 */
	public void loveLoadImage(String data, ImageView image, int imageWidth,Bitmap.Config config) {
		if(FileLove.isText(data)){
		ImageData mData = new ImageData(data,image,imageWidth,config, ImageData.IMAGE_TYPE_NORMAL);
		loadAsImage(mData, image,mLoadingBitmap);
		}else{
			Log.w(TAG, "loveLoadImage: url "+String.valueOf(data));
		}
	}
	
	
	
	
	 /**
	  * 单纯的下载图片文件,然后在通过{@link OnFetchCompleteListener}接口回调数据
	 * @param data 图片的url数据
	 * @param callback 回调接口
	 */
	public final void loveSimpleLoadBitmap(String data,OnFetchCompleteListener callback) {
		if(FileLove.isText(data)){
		 SimpleBitmapTask task = new SimpleBitmapTask(this, data, callback);
		 task.start();
		}else{
			Log.w(TAG, "loveSimpleLoadBitmap: url "+String.valueOf(data));			
		}
	}
	
	 /**
	  * 单纯的下载一组图片文件,然后在通过{@link OnAllFetchCompleteListener}接口回调数据
	 * @param datas 图片的URL数据
	 * @param taskId  任务ID，回调通知
	 * @param callback 回调接口
	 */
	public final void loveSimpleLoadBitmapAsList(List<String> datas,int taskId,OnAllFetchCompleteListener callback) {
		 SimpleBitmapTasks task = new SimpleBitmapTasks(this, datas,taskId, callback);
		 task.start();
	}
	
	/**
	 * 多线程下载图片
	 * @param data
	 *            图片URL
	 * @param image
	 *            view组件
	 * @param imageWidth
	 *            图片的宽度,可以设置小于0的数字，大于0则按照图片宽度缩放图片.
	 * @param config
	 *            Bitmap.Config 颜色加载模式
	 */
	public void loveLoadImageAsTasks(String data, ImageView image, int imageWidth,
			Bitmap.Config config) {
		if(FileLove.isText(data)){
		ImageData mData = new ImageData(data, image,imageWidth,config,ImageData.IMAGE_TYPE_NORMAL);
		loadAsImageAsTask(mData, image,mLoadingBitmap);
		}else{
			
			Log.w(TAG, "loveLoadImageAsTasks: url "+String.valueOf(data));
		}
	}
	/**
	 * 多线程下载图片,无压缩无缩放加载bitmap图片，本方法适用主页大图LOGO,方法比较危险
	 * @param data 图片URL
	 * @param image  view组件
	 * @param config itmap.Config 颜色加载模式
	 */
	public void loveLoadImageNoCompressAsTasks(String data, ImageView image,
			Bitmap.Config config) {
		if(FileLove.isText(data)){
		ImageData mData = new ImageData(data, image,-100,config,ImageData.IMAGE_TYPE_NORMAL);
		loadAsImageAsTask(mData, image,mLoadingBitmap);
		}else{
			Log.w(TAG, "loveLoadImageNoCompressAsTasks: url "+String.valueOf(data));
		}
	}
	
	
	/**
	 * @param data 图片URL
	 * @param image ImageView
	 * @param config 颜色加载模式
	 */
	public void loveLoadImageIcon(String data, ImageView image,Bitmap.Config config) {
		if(FileLove.isText(data)){
		ImageData mData = new ImageData(data,image,0,config,ImageData.IMAGE_TYPE_THUMBNAIL);
		loadAsImageIcon(mData, image,mLoadingBitmap);
		}else{
			Log.w(TAG, "loveLoadImageIcon: url "+String.valueOf(data));
		}
	}
	
	/**
	 * @param data 图片URL
	 * @param image ImageView
	 * @param config 颜色加载模式
	 */
	public void loveLoadImageIconAsNoCompress(String data, ImageView image,Bitmap.Config config) {
		if(data!=null&&data.length()>0){
		ImageData mData = new ImageData(data,image,-100,config,ImageData.IMAGE_TYPE_THUMBNAIL);
		loadAsImageIcon(mData, image,mLoadingBitmap);
		}else
		{
			Log.w(TAG, "loveLoadImageIconAsNoCompress: url "+String.valueOf(data));
		}
	}
	
	private void loadAsImageIcon(ImageData data, ImageView imageView,Bitmap loadingBitmap){
		Bitmap bitmap = null;

		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCacheAsIcon(String.valueOf(data),data.bitConfig);
		}
		if (mImageCache != null && !isExitTasksEarly()) {
			bitmap = mImageCache.getBitmapFromDiskCacheIcon(String.valueOf(data),data.bitConfig);
			if (bitmap != null && mImageCache != null) {
				mImageCache.addBitmapToCache(String.valueOf(data), bitmap);
			}
		}
		
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap);
		} else if (cancelPotentialWork(data, imageView)) {
			if (mLoadingBitmap != null) {
				imageView.setImageBitmap(mLoadingBitmap);
			}
			mBitmapThread.addBitmapInfo(data);
		}
		bitmap = loadLocationImage(data,data.imageWidth,data.bitConfig);
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap);
		}
	}
	
	/**
	 * 多线程下载图片
	 * @param data 图片URL
	 * @param image ImageView
	 * @param config 颜色加载模式
	 */
	public void loveLoadImageIconAsTasks(String data, ImageView image,Bitmap.Config config) {
		ImageData mData = new ImageData(data,image,0, config,ImageData.IMAGE_TYPE_THUMBNAIL);
		loadAsImageIconAsTasks(mData, image,mLoadingBitmap);
	}

	private void loadAsImageIconAsTasks(ImageData data, ImageView imageView,Bitmap loadingBitmap){
		Bitmap bitmap = loadLocationImage(data,data.bitConfig);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		} else if (cancelPotentialWork(data, imageView)) {
			LoveBitmapTasks tasks = new LoveBitmapTasks(this, new LoveBitmapHandler(mImageCache, this),LoveBitmapTasks.MODE_DEFAULT, data);
			final AsyncDrawableLove asyncDrawable = new AsyncDrawableLove(mContext.getResources(), loadingBitmap, tasks);
			imageView.setImageDrawable(asyncDrawable);
			executorService.execute(tasks);
		}
		bitmap = loadLocationImage(data,data.imageWidth,data.bitConfig);
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap);
		}
	}
	 Bitmap loadLocationImage(Object data,Bitmap.Config config)
	{
		Bitmap bitmap = null;
		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCacheAsIcon(String.valueOf(data), config);
			if(bitmap!=null)
				return bitmap;
		}
		if (mImageCache != null && !isExitTasksEarly()) {
			bitmap = mImageCache.getBitmapFromDiskCacheIcon(String.valueOf(data),config);
		}
		if (bitmap != null && mImageCache != null) {
			mImageCache.addBitmapToCache(String.valueOf(data), bitmap);
		}
		return bitmap;
	}
	
	/**
	 * @param data
	 * @param imageView
	 * @param loadingBitmap
	 */
	private void loadAsImageAsTask(ImageData data, ImageView imageView,
			Bitmap loadingBitmap) {
		Bitmap bitmap = loadLocationImage(data,data.imageWidth,data.bitConfig);
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap);
		} /*else if (cancelPotentialWork(data, imageView)) {
			LoveBitmapTasks tasks = new LoveBitmapTasks(this, loveBitmapHandler, data);
			final AsyncDrawableLove asyncDrawable = new AsyncDrawableLove(mContext.getResources(), loadingBitmap, tasks);
			imageView.setImageDrawable(asyncDrawable);
			executorService.execute(tasks);
		}  */else {
			LoveBitmapTasks tasks = new LoveBitmapTasks(this, new LoveBitmapHandler(mImageCache,this),LoveBitmapTasks.MODE_DEFAULT, data);
			final AsyncDrawableLove asyncDrawable = new AsyncDrawableLove(mContext.getResources(), loadingBitmap, tasks);
			imageView.setImageDrawable(asyncDrawable);
			executorService.execute(tasks);
		}
	}
	
	/**
	 * @param data
	 * @param imageView
	 * @param loadingBitmap
	 */
	private void loadAsImage(ImageData data, ImageView imageView,
			Bitmap loadingBitmap) {
		Bitmap bitmap = loadLocationImage(data,data.imageWidth,data.bitConfig);
		if (bitmap != null) {
			setImageBitmap(imageView, bitmap);
		} else if (cancelPotentialWork(data, imageView)) {
			if (mLoadingBitmap != null) {
				imageView.setImageBitmap(mLoadingBitmap);
			}
			mBitmapThread.addBitmapInfo(data);
		}
		bitmap = loadLocationImage(data,data.imageWidth,data.bitConfig);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		}
	}
	
	
	
	 Bitmap loadLocationImage(ImageData data,int reqWidth,Bitmap.Config config)
	{
		Bitmap bitmap = null;
		if (mImageCache != null) {
			bitmap = mImageCache.getBitmapFromMemCache(String.valueOf(data),
					reqWidth, config);
			if(bitmap!=null)
				return bitmap;
		}
		if (mImageCache != null && !isExitTasksEarly()) {
			bitmap = mImageCache.getBitmapFromDiskCache(String.valueOf(data),
					reqWidth, config);
		}
		if (bitmap != null && mImageCache != null) {
			mImageCache.addBitmapToCache(String.valueOf(data), bitmap);
		}
		return bitmap;
	}
	/**
	 * 设置一个默认显示的图片,一般是一张加载中的图片
	 * 
	 * @param bitmap
	 */
	public void setLoadingImage(Bitmap bitmap) {
		mLoadingBitmap = bitmap;
	}

	/**
	 * 设置一个默认显示的图片,一般是一张加载中的图片
	 * 
	 * @param resId
	 */
	public void setLoadingImage(int resId) {
		mLoadingBitmap = BitmapFactory.decodeResource(mContext.getResources(),
				resId);
	}

//	/**
//	 * @param fadeIn
//	 */
//	public void setImageFadeIn(boolean fadeIn) {
//		mFadeInBitmap = fadeIn;
//	}

	/**
	 * 设置退出下载任务
	 * 
	 * @param exitTask
	 */
	public void setExitTasksEarly(boolean exitTask) {
		mExitTasksEarly = exitTask;
	}

//	/**
//	 * @param data
//	 * @return
//	 */
//	protected Bitmap processBitmap(Object data, int reqWidth,
//			Bitmap.Config bcofnig) {
//		try {
//			final ImageData imageData = (ImageData) data;
//			return processBitmap(imageData.mKey, imageData.mType, reqWidth,
//					bcofnig);
//		} catch (Exception ex) {
//			ex.printStackTrace();
//		}
//		return null;
//	}
//
//	/**
//	 * @param key
//	 * @param type
//	 * @return
//	 */
//	private Bitmap processBitmap(String key, int type, int reqWidth,
//			Bitmap.Config config) {
//		Log.d(TAG, "processBitmap - " + key);
//		Bitmap bm = null;
//		if (type == ImageData.IMAGE_TYPE_NORMAL) {
//			final File f = HttpLove.downloadBitmapToFile(mContext, key);
//			if (f != null) {
//				try {
//					if (reqWidth > 0) {
//						bm = BitmapLove.decodeSampledBitmapFromFile(f.toString(),
//								reqWidth, config);
//					} else {
//
//						BitmapFactory.Options opts = BitmapLove.getBitmapWidthAndHeigth(f
//								.toString());
//						int imgWidth = opts.outWidth;
//						if (imgWidth > ScreenWidth) {
//							bm = BitmapLove.decodeSampledBitmapFromFile(f.toString(),
//									ScreenWidth, config);
//						} else {
//							bm = BitmapFactory.decodeFile(f.toString(),
//									Config.getIconOptions(2, config));
//						}
//					}
//				} catch (Exception e) {
//					e.printStackTrace();
//				}
//
//			}
//		} else if (type == ImageData.IMAGE_TYPE_THUMBNAIL) {
//			final File f = HttpLove.downloadBitmapToFile(mContext, key);
//			if (f != null) {
//				if (reqWidth > 0) {
//					bm = BitmapLove.decodeSampledBitmapFromFile(f.toString(), reqWidth,
//							config);
//				} else {
//					bm = BitmapFactory.decodeFile(f.toString(),
//							Config.getIconOptions(2, config));
//				}
//			}
//		}
//		return bm;
//	}

	

	/**
	 * 判断当前图片是否正在下载任务中.
	 * 
	 * @param image
	 * @return isWorking
	 */
	public static boolean isWorking(ImageView image) {
		final LoveBitmapTasks bitmapWorkerTask = getBitmapWorkerTask(image);
		if (bitmapWorkerTask != null) {
			return true;
		}
		return false;
	}

	/**
	 * 取消当前图片的下载任务
	 * 
	 * @param image
	 */
	public static void cancelWork(ImageView image) {
		final LoveBitmapTasks bitmapWorkerTask = getBitmapWorkerTask(image);
		if (bitmapWorkerTask != null) {
			bitmapWorkerTask.setCancel(true);
		}
	}

	/**
	 * 取消当前指定图片的下载任务
	 * 
	 * @param data
	 * @param image
	 * @return boolean
	 */
	public static boolean cancelPotentialWork(Object data, ImageView image) {
		final LoveBitmapTasks bitmapWorkerTask = getBitmapWorkerTask(image);

		if (bitmapWorkerTask != null) {
			final Object bitmapData = bitmapWorkerTask.queue;
			if (bitmapData == null || !bitmapData.equals(data)) {
				bitmapWorkerTask.setCancel(true);
				Log.v(TAG, "cancelPotentialWork - cancelled work for " + data);
			} else {
				// The same work is already in progress.
				return false;
			}
		}
		return true;
	}

	 static LoveBitmapTasks getBitmapWorkerTask(ImageView image) {
		if (image != null) {
			final Drawable drawable = image.getDrawable();
			if (drawable instanceof AsyncDrawableLove) {
				final AsyncDrawableLove asyncDrawable = (AsyncDrawableLove) drawable;
				return asyncDrawable.getBitmapWorkerTask();
			}
		}
		return null;
	}


	void setImageBitmap(ImageView imageView, Bitmap bitmap) {
		if (mFadeInBitmap) {
			final TransitionDrawable td = new TransitionDrawable(
					new Drawable[] {
							new ColorDrawable(android.R.color.transparent),
							new BitmapDrawable(mContext.getResources(), bitmap) });
			imageView.setImageDrawable(td);
			td.startTransition(FADE_IN_TIME);
		} else {
			imageView.setBackgroundDrawable(null);
			imageView.setImageBitmap(bitmap);

		}
	}
	public boolean isExitTasksEarly() {
		return mExitTasksEarly;
	}

}
